package Reflex.secondStudy;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import static java.lang.Class.forName;

public class TestReflex {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
        User user = new User();
        //TODO  第一步 : 获取需要反射的类
        /**
         * 有三种方式 :
         */
        Class clazz1 = user.getClass();
        Class clazz2 = User.class;
        Class clazz3 = Class.forName("Reflex.secondStudy.User");
        System.out.println("=================================================================================");

        //TODO  第二步 ：newInstance 创建实例化对象
        Object obj = clazz1.newInstance();
        System.out.println("=================================================================================");

        //TODO  第三步 ： 获取  1.属性(Filed)  或者 2.方法(Method)
        System.out.println("-------All Method-----");
        //获取所有的方法
        Method[] methods = clazz1.getMethods();
        for(Method m : methods){
            System.out.println(m.getName());
        }
        System.out.println("-------All Field(只能访问 public 属性)-----");
        //获取所有的属性
        Field[] fields = clazz1.getFields();
        for(Field f : fields){
            System.out.println(f.getName());
        }

        //TODO 第四步 ： 1. 访问 public方法
        System.out.println("====================================获取某个 public 方法或者属性==========================================");
        System.out.println("-------------method--------------");
        System.out.println("有参 :");
        Method setAge =  clazz1.getMethod("setAge",Integer.class);
        Integer returnAge = (Integer) setAge.invoke(obj,22);
        System.out.println(returnAge);
        System.out.println("无参 :");
        Method getAge = clazz1.getMethod("getAge",new Class[]{});  //空类
        Integer returnAge2 = (Integer) getAge.invoke(obj,new Object[]{});
        System.out.println(returnAge2);


        System.out.println("-----------field -----------------");
        Field nameAliasField = clazz1.getField("nameAlias");
        nameAliasField.set(obj, "阿珠");
        System.out.println((User) obj);

        //TODO  第四步 : 2.访问 private方法或者属性 ： 需要method或者field  调用  setAccessible(true);
        System.out.println("==================================获取某个 private 方法 或 属性 ==========================================");
        System.out.println("-------------method--------------");
        Method privateMethod = clazz1.getDeclaredMethod("privateMethod", String.class);
        privateMethod.setAccessible(true);  //私有方法需要 暴力破解
        privateMethod.invoke(obj,"Rose");

        System.out.println("------------field---------------");
        Field privateField = clazz1.getDeclaredField("name");
        privateField.setAccessible(true);
        privateField.set(obj,"秦");
        System.out.println(((User) obj).getName());

        //TODO 第四步 ： 3. 访问 static 方法
        System.out.println("===============================获取某个类的 static 方法=================================================");
        Method staticMethod = clazz1.getMethod("staticMethod", String.class);
        staticMethod.invoke(null,"明");

    }
}
